package com.ruyuan.eshop.diplomacy.api.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ruyuan.eshop.common.core.JsonResult;
import com.ruyuan.eshop.common.utils.BeanCopyUtil;
import com.ruyuan.eshop.diplomacy.api.ProductCollectApi;
import com.ruyuan.eshop.common.constants.diplomacy.BaseConstants;
import com.ruyuan.eshop.diplomacy.converter.ProductDetailConverter;
import com.ruyuan.eshop.diplomacy.domain.bo.*;
import com.ruyuan.eshop.diplomacy.domain.dto.*;
import com.ruyuan.eshop.diplomacy.domain.query.ProductCollectQuery;
import com.ruyuan.eshop.common.enums.PriceTypeEnum;
import com.ruyuan.eshop.common.exception.ProductErrorCodeEnum;
import com.ruyuan.eshop.diplomacy.domain.query.ProductDetailQuery;
import com.ruyuan.eshop.diplomacy.manager.custom.cache.ItemCollectCache;
import com.ruyuan.eshop.diplomacy.manager.custom.cache.ProductDetailCache;
import com.ruyuan.eshop.diplomacy.manager.custom.cache.SkuCollectCache;
import com.ruyuan.eshop.diplomacy.manager.custom.cache.SkuPriceSellerCache;
import com.ruyuan.eshop.common.utils.diplomacy.NumberUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品综合信息服务
 *
 * @author zhonghuashishan
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = ProductCollectApi.class, retries = 0)
public class ProductCollectApiImpl implements ProductCollectApi {

    @Resource
    private ItemCollectCache itemCollectCache;

    @Resource
    private SkuCollectCache skuCollectCache;

    @Resource
    private SkuPriceSellerCache skuPriceSellerCache;

    @Resource
    private ProductDetailCache productDetailCache;

    @Resource
    private ProductDetailConverter productDetailConverter;
    /**
     * 卖家类型
     */
    public static final String SELLER_TYPE = "sellerType";

    /**
     * 卖家ID
     */
    public static final String SELLER_ID = "sellerId";

    /**
     * 商品ID
     */
    public static final String SKU_ID = "skuId";

    /**
     * 根据itemId或skuId获取商品信息
     *
     * @param productCollectQuery
     * @return com.ruyuan.eshop.common.core.JsonResult<com.ruyuan.eshop.diplomacy.domain.dto.ProductCollectDTO>
     * @author zhonghuashishan
     */
    @Override
    public JsonResult<Map<String, ProductCollectDTO>> getProductCollect(ProductCollectQuery productCollectQuery) {
        if(Objects.isNull(productCollectQuery) || CollectionUtils.isEmpty(productCollectQuery.getProductIdList())) {
            return JsonResult.buildError(ProductErrorCodeEnum.PARAM_ERROR.getErrorCode(), ProductErrorCodeEnum.PARAM_ERROR.getErrorMsg());
        }

        if(productCollectQuery.getProductIdList().size() > BaseConstants.LIMIT_100) {
            return JsonResult.buildError(ProductErrorCodeEnum.PRODUCT_LIMIT_ERROR.getErrorCode(), ProductErrorCodeEnum.PRODUCT_LIMIT_ERROR.getErrorMsg());
        }

        Set<String> productIdSet = Sets.newHashSet(productCollectQuery.getProductIdList());
        Set<String> itemIdSet = productIdSet.stream().filter(NumberUtils::isItem).collect(Collectors.toSet());

        List<ItemInfoBO> itemInfoBOList = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(itemIdSet)) {
            Optional<List<ItemInfoBO>> itemOptional = itemCollectCache.listRedisStringData(Lists.newArrayList(itemIdSet));
            if(itemOptional.isPresent()) {
                itemInfoBOList = itemOptional.get();
            }
        }
        // 获取sku相关信息
        ProductBO productBO = buildSkuInfoList(productCollectQuery, itemInfoBOList);

        return JsonResult.buildSuccess(buildProductCollect(productBO.getItemInfoBOList(),productBO.getSkuInfoBOList(),productBO.getPriceBOList()));
    }

    /**
     * 根据skuId获取商品详情
     *
     * @param productDetailQuery
     * @return com.ruyuan.eshop.common.core.JsonResult<com.ruyuan.eshop.diplomacy.domain.dto.ProductCollectDTO>
     * @author zhonghuashishan
     */
    @Override
    public JsonResult<ProductDetailDTO> getProductDetail(ProductDetailQuery productDetailQuery) {
        if(Objects.isNull(productDetailQuery) || Objects.isNull(productDetailQuery.getSkuId())) {
            return JsonResult.buildError(ProductErrorCodeEnum.PARAM_ERROR.getErrorCode(), ProductErrorCodeEnum.PARAM_ERROR.getErrorMsg());
        }

        List<String> productIdList = Arrays.asList(productDetailQuery.getSkuId());

        Optional<List<ProductDetailBO>> optional = productDetailCache.listRedisStringData(productIdList);
        if (optional.isPresent()){
            List<ProductDetailBO> productDetailBOS = optional.get();

            ProductDetailDTO productDetailDTO = productDetailConverter.converterDetail(productDetailBOS.get(0));
            return JsonResult.buildSuccess(productDetailDTO);
        }
        return JsonResult.buildSuccess();
    }

    /**
     * 构建商品相关信息
     */
    private ProductBO buildSkuInfoList(ProductCollectQuery productCollectQuery, List<ItemInfoBO> itemInfoBOList){
        Set<String> productIdSet = Sets.newHashSet(productCollectQuery.getProductIdList());
        Set<String> itemIdSet = productIdSet.stream().filter(NumberUtils::isItem).collect(Collectors.toSet());
        Set<String> skuIdSet = Sets.difference(productIdSet, itemIdSet);

        List<SkuInfoBO> skuInfoBOList = Lists.newArrayList();
        List<SkuPriceSellerRelationBO> priceBOList = Lists.newArrayList();

        if(!CollectionUtils.isEmpty(skuIdSet)) {
            Optional<List<SkuInfoBO>> skuOptional = skuCollectCache.listRedisStringData(Lists.newArrayList(skuIdSet));
            if(skuOptional.isPresent()) {
                skuInfoBOList = skuOptional.get();
            }
            // 获取配置价格，该价格以卖家商品价格关系为准
            if(Objects.nonNull(productCollectQuery.getSellerType()) && StringUtils.isNotBlank(productCollectQuery.getSellerId())) {
                Map<String, Object> requestMap = Maps.newHashMap();
                Integer sellerType = productCollectQuery.getSellerType();
                String sellerId = productCollectQuery.getSellerId();
                requestMap.put(SELLER_TYPE, sellerType);
                requestMap.put(SELLER_ID, sellerId);
                List<String> keyList = Lists.newArrayList();
                skuIdSet.stream().forEach(sku -> {
                    keyList.add(sku + sellerType + sellerId);
                });
                Optional<List<SkuPriceSellerRelationBO>> priceOptional = skuPriceSellerCache.listRedisStringData(keyList, requestMap);
                if(priceOptional.isPresent()) {
                    priceBOList = priceOptional.get();
                }
            }
        }
        return new ProductBO(itemInfoBOList, skuInfoBOList, priceBOList);
    }

    /**
     * 构建商品信息
     *
     * @param itemInfoBOList
     * @param skuInfoBOList
     * @param priceBOList
     * @return java.util.Map<java.lang.String,com.ruyuan.eshop.diplomacy.domain.dto.ProductCollectDTO>
     * @author zhonghuashishan
     */
    private Map<String, ProductCollectDTO> buildProductCollect(List<ItemInfoBO> itemInfoBOList, List<SkuInfoBO> skuInfoBOList, List<SkuPriceSellerRelationBO> priceBOList) {
        if(CollectionUtils.isEmpty(itemInfoBOList) && CollectionUtils.isEmpty(skuInfoBOList)) {
            return null;
        }

        Map<String, ProductCollectDTO> productCollectMap = Maps.newHashMap();
        if(!CollectionUtils.isEmpty(itemInfoBOList)) {
            for (ItemInfoBO itemInfoBO : itemInfoBOList) {
                productCollectMap.put(itemInfoBO.getItemId(), convertItem2Product(itemInfoBO));
            }
        }

        if(!CollectionUtils.isEmpty(skuInfoBOList)) {
            for (SkuInfoBO skuInfoBO : skuInfoBOList) {
                productCollectMap.put(skuInfoBO.getSkuId(), convertSku2Product(skuInfoBO));

            }
        }

        if(CollectionUtils.isEmpty(priceBOList)) {
            return productCollectMap;
        }

        for (Map.Entry<String, ProductCollectDTO> entry : productCollectMap.entrySet()) {
            String productId = entry.getKey();
            for (SkuPriceSellerRelationBO price : priceBOList) {
                if(!Objects.equals(productId, price.getSkuId())) {
                    continue;
                }
                PriceBaseDTO priceBaseDTO = entry.getValue().getPriceBase();
                Integer priceType = price.getPriceType();
                if(Objects.equals(PriceTypeEnum.BASE_PRICE.getCode(), priceType)) {
                    priceBaseDTO.setBasePrice(price.getPrice());
                }
                if(Objects.equals(PriceTypeEnum.VIP_PRICE.getCode(), priceType)) {
                    priceBaseDTO.setVipPrice(price.getPrice());
                }
            }
        }

        return productCollectMap;
    }

    /**
     * item转Product
     *
     * @param itemInfoBO
     * @return com.ruyuan.eshop.diplomacy.domain.dto.ProductCollectDTO
     * @author zhonghuashishan
     */
    private ProductCollectDTO convertItem2Product(ItemInfoBO itemInfoBO) {
        ProductCollectDTO productCollectDTO = new ProductCollectDTO();
        ItemBaseDTO itemBaseDTO = new ItemBaseDTO();
        BeanUtils.copyProperties(itemInfoBO, itemBaseDTO);
        productCollectDTO.setItemBase(itemBaseDTO);
        List<SkuInfoBO> skuInfoBOList = itemInfoBO.getSkuInfoBOList();
        if(!CollectionUtils.isEmpty(skuInfoBOList)) {
            List<SkuBaseDTO> skuBaseDTOList = BeanCopyUtil.copyListProperties(skuInfoBOList, SkuBaseDTO::new);
            itemBaseDTO.setSkuBaseList(skuBaseDTOList);
        }

        CategoryBaseDTO categoryBaseDTO = new CategoryBaseDTO();
        BeanUtils.copyProperties(itemInfoBO, categoryBaseDTO);
        productCollectDTO.setCategoryBase(categoryBaseDTO);

        return productCollectDTO;
    }

    /**
     * sku转Product
     *
     * @param skuInfoBO
     * @return com.ruyuan.eshop.diplomacy.domain.dto.ProductCollectDTO
     * @author zhonghuashishan
     */
    private ProductCollectDTO convertSku2Product(SkuInfoBO skuInfoBO) {
        ProductCollectDTO productCollectDTO = new ProductCollectDTO();
        ItemBaseDTO itemBaseDTO = new ItemBaseDTO();
        BeanUtils.copyProperties(skuInfoBO, itemBaseDTO);
        productCollectDTO.setItemBase(itemBaseDTO);

        PriceBaseDTO priceBaseDTO = new PriceBaseDTO();
        BeanUtils.copyProperties(skuInfoBO, priceBaseDTO);
        productCollectDTO.setPriceBase(priceBaseDTO);

        CategoryBaseDTO categoryBaseDTO = new CategoryBaseDTO();
        BeanUtils.copyProperties(skuInfoBO, categoryBaseDTO);
        productCollectDTO.setCategoryBase(categoryBaseDTO);

        return productCollectDTO;
    }
}
